<?php
/**
 * Created by PhpStorm.
 * User: yunzhi.liu
 * Date: 2020/9/25
 * Time: 10:33
 */

namespace app\strategy\pay;


use app\strategy\pay\PayInterface;

use app\models\order\OrderModel;
use app\models\user\UserModel;
use app\services\config\ConfigService;
use app\services\order\OrderService;


use think\facade\Db;

require_once '../extend/AlipaySDK/aop/AopClient.php';
require_once '../extend/AlipaySDK/aop/request/AlipayTradeAppPayRequest.php';

require_once '../extend/AlipaySDK/aop/AopCertClient.php';
require_once '../extend/AlipaySDK/aop/AopCertification.php';
require_once '../extend/AlipaySDK/aop/AlipayConfig.php';
require_once '../extend/AlipaySDK/aop/request/AlipayTradeRefundRequest.php';

class AliPay implements PayInterface
{
    private $ali_appId;
    private $certNo;
    private $privateKeyPath;
    private $platformKeyPath;
    private $merchantPrivateKeyInstance;

    public function __construct()
    {
        //$config = ConfigService::getConfigValueArray(['wechat_app_id', 'mch_id', 'cert_no', 'mch_private_key', 'platform_cert']);
    }

    /**
     * 获取实例
     * @return \WeChatPay\BuilderChainable
     * @throws \Exception
     */
    public function getInstance()
    {
        try {
            $aop = new \AopClient;
            $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
            $aop->appId = "2021004143623046";
            $aop->rsaPrivateKey = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCF4OWO1Fp/aR1+P7qeIf67gV4eFl+iBd2g92w8W4L3qhANexkTVNZRq6DH+cWJtwab1OV0dkVKvPX9C3NNCT25T088MfeXJ0tAm8FjOjfTfEhdalGfDKI733ESZIHRPKHqskJmhsFPz/VkSPPnvzhSXAfZJdKLIK9wmx1rmvhTQeoAb2eeixzCmBuIRGI1JBC018ufrwa47zqi8Ngm5hWuhp850WGfEedgY0L9D/A4aG91GVy1LZfjItS9LvXNr59FuFuUWy2LVizLbj0ATtHfMSHparFpadl5b17AnwBqjxdMmPtlcs3VjXv5pxymfRhtvlKjvHI+1N0+1TiBrw2nAgMBAAECggEAbFsZESAYWvUF1O/ZqDFVjgdn2Kw9HNLojWaUaMmcV72CHpcaNYY9rH5ftFsZIZxMMgX+7OLotFP6OKNy38/x8DEbrVm3zdQU2Sb3P8uX8YiuvUTW6Qb9q73uM3e7hlEvr9g1W+wHPATR1SgimNgwyqAIDh3Jqad7t4UkK7qS8DbFDSwA3+3sAiEqDNR3NzWpVE9JdD24/3BvIGXu42GeLkrGLyVffN2BdNtXOEJpOIcN+onIyZUA9WBBSUbe4Mgr64iAgk8tpb4v1TnAK78gwPrUUbQErRKqYcIDUjedP/5bJaVRZTiFaAUph0Yug7l1Yq1i3l/shUE0I6Dwfo8dOQKBgQDL6wHwF3nEhfKwQqZqs6fD44CW678FFATNTNaLPCV8LTJMT7RE9fYfrj7+zawhIjsBBk1TfaoJvpzVvcK5xT4RXFPfMVuD1nLwBMsQ4NtF41J+P/T5GuRO/z916VtIYA4VjiuLl6wudWzWIsvdlpD4cyn040BmjcoAAd4ALhCuhQKBgQCoEmuqnm2KkKWIs9xykVNyqSKDheTe/aPNL9qvGKrEhuseVShjTTTncjf5+nATMzr0/IbIQOH4EWBmqxjuqihCWSDcJU0WEQMpEXnAWYsz6dwr8Fi1F4x6mgTzU8chmSzf4fm+9jS543AiReGkZSPWwQNLo9ntRU1TLbgYu0AROwKBgQCXE1NqN1pFmR+GKrr0jomafXCFX78z2fL8zxKcMUFsUGfVVa+u77MbIZMWX/ZIzf188thTJOTXN1sml+Iuk806O3cAAqdUc4rP/B0eMhkCHDq/wk6SR7QiOsUfbHXulwuYOK5WS1aLTQAHXdxAHQ7moxvQjJTn5eBkRP3ekEJXqQKBgQCFfeQAJ0dP+GVR97GPWbgS6R2dozpOltyEO48Q5aG06IhUlkS24nqznbeyF+TuixE3xl7zLP2Nv5d21EzAO2wwjoQX9pSMg0SkWNoAGd8Dg6q5R3Pdme+c7TojXhZarEPFKsHnl7v3LRtCTYjTvvVBPBp2+JQ97X5mI3kGQ6u2QwKBgCQ4v4ayekU6KSyf6sP9uCn6Jp34yMuqS5bBeoiuZHg2lHoHWLzlh78ZXzMwC8ijC+ISE4vaUSFsrh36vWplzpOYy50AcRW5cqb5E+ej3r7j4ryvt5jpweoMx8xQm7ZkUHry42Md+aykDwBx0d8DxODujS0sNr6gaglQ/pvcidvx';
            //支付宝公钥
            $aop->alipayrsaPublicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArxCK1KnV4MnXOKsDkKfMwUB1s0maYZW7SFhbbF0ob2Y947YA8m8nwZ5wI9Ulfwfb1hhAUWulqOEoL5qZztK+TTyh5HlAmkl5xzdxkGrdCE1WTGiY+m4k5vJQTKVACbDinc3vchbXbVps+76d2yv+OMfJVska3CKjywSGH4sqLRnR9cZk09FoFVctJvCB85Tm+3WuHTOPXwE1/M+94d2vEDWdWC3/aEFS/xO0kt7GQNkr4uGqtN3u/B4CBhaJLYck4iPbzRSCgagTnuaiw5wiiuaoJ/UHu486Iobql3lhclsEWibhMZ2qMJuT3q3vC7sCc/pmu29bsFCT4bbHgwm4JwIDAQAB';
            $aop->format = "json";
            $aop->charset = "UTF-8";
            $aop->signType = "RSA2";

            return $aop;
        } catch (\Exception $exception) {
            throw new \Exception($exception->getMessage());
        }
    }


    /**
     * 支付宝支付
     * @param $body 我是测试数据
     * @param $subject App支付测试
     * @param $out_trade_no 订单号
     * @param $total_amount 金额,单位(元)
     * @param $notify_url 回调地址
     * @return string
     * @throws \Exception
     */
    public function pay($body, $subject, $out_trade_no, $total_amount = '0.01', $notify_url = '/api/Notify/aliPayNotify')
    {
        try {
            $aop = $this->getInstance();

            //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
            $request = new \AlipayTradeAppPayRequest();

            //SDK已经封装掉了公共参数，这里只需要传入业务参数
            $bizcontent = "{\"body\":\"{$body}\","
                . "\"subject\": \"{$subject}\","
                . "\"out_trade_no\": \"{$out_trade_no}\","
                . "\"timeout_express\": \"30m\","
                . "\"total_amount\": \"{$total_amount}\","
                . "\"product_code\":\"QUICK_MSECURITY_PAY\""
                . "}";
            //$request->setNotifyUrl(request()->domain() . '/api/Notify/aliPayNotify');
            $request->setNotifyUrl($notify_url);

            $request->setBizContent($bizcontent);
            //这里和普通的接口调用不同，使用的是sdkExecute
            $response = $aop->sdkExecute($request);
            //htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义，实际打印到日志以及http传输不会有这个问题
            return $response; //htmlspecialchars($response);

        } catch (\Exception $exception) {
            throw new \Exception($exception->getMessage());
        }
    }


    /**
     * 退款
     * @param $orderId
     * @param $cancelType
     * @return void
     * @throws \Exception
     */
    public function refund($orderId, $cancelType)
    {
        try {
            $alipayClient = $this->getInstance();

            //查找订单信息
            $orderInfo = OrderModel::find($orderId);
            //计算退款金额
            $amount = $orderInfo['pay_amount'];
            if ($amount <= 0) {
                return true;
            }

            // 构造请求参数以调用接口
            $request = new \AlipayTradeRefundRequest();
            $model = array();

            // 设置商户订单号
            $model['out_trade_no'] = $orderInfo['union_order_sn'];

            // 设置查询选项
            $queryOptions = array();
            $queryOptions[] = "refund_detail_item_list";    //退款资金渠道
            $model['query_options'] = $queryOptions;

            // 设置退分账明细信息
//            $refundRoyaltyParameters = array();
//            $refundRoyaltyParameters0 = array();
//            $refundRoyaltyParameters0['amount'] = "0.1";
//            $refundRoyaltyParameters0['trans_in'] = "2088101126708402";
//            $refundRoyaltyParameters0['royalty_type'] = "transfer";
//            $refundRoyaltyParameters0['trans_out'] = "2088101126765726";
//            $refundRoyaltyParameters0['trans_out_type'] = "userId";
//            $refundRoyaltyParameters0['royalty_scene'] = "达人佣金";
//            $refundRoyaltyParameters0['trans_in_type'] = "userId";
//            $refundRoyaltyParameters0['trans_in_name'] = "张三";
//            $refundRoyaltyParameters0['desc'] = "分账给2088101126708402";
//            $refundRoyaltyParameters[] = $refundRoyaltyParameters0;
//            $model['refund_royalty_parameters'] = $refundRoyaltyParameters;

            // 设置支付宝交易号 ,与商户订单号可二选一,同时存在时,本参数优先级高
            //$model['trade_no'] = "2014112611001004680073956707";

            // 设置退款金额
            //$model['refund_amount'] = $amount;
            $model['refund_amount'] = '0.01';

            // 设置退款包含的商品列表信息
//            $refundGoodsDetail = array();
//            $refundGoodsDetail0 = array();
//            $refundGoodsDetail0['out_sku_id'] = "outSku_01";
//            $refundGoodsDetail0['out_item_id'] = "outItem_01";
//            $refundGoodsDetail0['goods_id'] = "apple-01";
//            $refundGoodsDetail0['refund_amount'] = "19.50";
//            $refundGoodsDetail[] = $refundGoodsDetail0;
//            $model['refund_goods_detail'] = $refundGoodsDetail;

            // 设置退款原因说明
            $model['refund_reason'] = "正常退款";

            // 设置针对账期交易
//            $model['related_settle_confirm_no'] = "2024041122001495000530302869";

            // 设置退款请求号, 部分退款下使用

            if(empty($orderInfo['request_no'])){
                $orderSn = createOrderSn();
                OrderModel::where('id',$orderInfo['id'])->update(['request_no' => $orderSn]);
            }else{
                $orderSn = $orderInfo['request_no'];
            }
            $model['out_request_no'] = $orderSn;

            $request->setBizContent(json_encode($model, JSON_UNESCAPED_UNICODE));
            $responseResult = $alipayClient->execute($request);
            $responseApiName = str_replace(".", "_", $request->getApiMethodName()) . "_response";
            $response = $responseResult->$responseApiName;

            if (!empty($response->code) && $response->code == 10000) {

                //退款成功 修改状态
                $orderInfo->refund_transaction_id = $response->trade_no;
                $orderInfo->refund_price = $response->refund_fee;
                $orderInfo->order_status = 0;
                $orderInfo->refund_time = time();
                $orderInfo->refund_fee = $response->refund_fee;
                $orderInfo->send_back_fee = $response->send_back_fee;
                $orderInfo->save();
                return true;
            } else {
                throw new \Exception('退款失败，请联系管理员');
            }
        } catch (\Exception $e) {
            // 进行错误处理
            throw new \Exception($e->getMessage());
        }
    }
}